import { createElement } from './dom.js';

const TopLevelWrapper = function(props) {
    this.props = props;
};

TopLevelWrapper.prototype.render = function() {
    return this.props;
};

const ReactReconciler = {
    mountComponent(internalInstance, container) {
        return internalInstance.mountComponent(container);
    }
};

class ReactCompositeComponentWrapper {
    constructor(element) {
        this._element = element;
    }

    mountComponent(container) {
        // 第一次this._element.type == TopLevelWrapper
        // 第二次this._element.type == createClass的Constructor函数
        const Component = this._element.type;
        const componentInstance = new Component(this._element.props);

        this._instance = componentInstance;

        if (componentInstance.componentWillMount) {
            componentInstance.componentWillMount();
        }
        
        const markup = this.performInitialMount(container);
        
        if (componentInstance.componentDidMount) {
            componentInstance.componentDidMount();
        }
        
        return markup;
    }
    
    performInitialMount(container) {

        // render()返回的就是props对象，我们知道ReactElement曾经被wrapperElement当作props包起来
        const renderedElement = this._instance.render();

        // 根据ReactElement的type的不同实例化
        const child = instantiateReactComponent(renderedElement);
        console.log(child)

        this._renderedComponent = child;

        // 这里其实是会递归调用，实例化了父组件，还要接着实例化子组件
        return ReactReconciler.mountComponent(child, container);
    }
}

function instantiateReactComponent(element) {
    if (typeof element.type === 'string') {
        return new ReactDOMComponent(element);
    } else if (typeof element.type === 'function') {
        return new ReactCompositeComponentWrapper(element);
    }
}

class ReactDOMComponent {
    constructor(element) {
        this._element = element;
    }

    mountComponent(container) {
        const domElement = document.createElement(this._element.type);
        const textNode = document.createTextNode(this._element.props.children);

        domElement.appendChild(textNode);
        container.appendChild(domElement);
        
        this._hostNode = domElement;
        return domElement;
    }
}

export function render(element, container){
    const wrapperElement = createElement(TopLevelWrapper, element);

    const componentInstance = new ReactCompositeComponentWrapper(wrapperElement);
        
    return ReactReconciler.mountComponent(componentInstance, container);

}
// class ReactDOMComponent {
//     constructor(element){
//         this._element = element;
//     }
// }
// export function render(element, container) {
    
// }

// export function render(element, container){
//     debugger;
// }